package speech.tag;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Scanner;

import be.ac.ulg.montefiore.run.jahmm.ObservationInteger;
import be.ac.ulg.montefiore.run.jahmm.io.ObservationIntegerReader;
import be.ac.ulg.montefiore.run.jahmm.io.ObservationSequencesReader;

public class HmmSpeechActTagger {
	Hashtable<String,TagWrapper> tags;
	int dictionarySize;
	
	public HmmSpeechActTagger(String configFile, int dicSize) {
		try {
			this.dictionarySize = dicSize;
			readConfigFile(configFile);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Read config file and initialize tag wrappers.
	 * 
	 * @param configFile
	 * @throws FileNotFoundException
	 */
	private void readConfigFile(String configFile) throws FileNotFoundException {
		try {
			BufferedReader r = new BufferedReader(new FileReader(configFile));

			tags = new Hashtable<String,TagWrapper>();
			String line;
			
			while ((line = r.readLine()) != null) {
				Scanner s = new Scanner(line);
				String tag = s.next();
				int noStates = s.nextInt();
				int delta = s.nextInt();
				String trainingFile = s.next();
				
				tags.put(tag, new TagWrapper(tag, noStates, dictionarySize, trainingFile, delta));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Train HMM models.
	 */
	public void train() {
		System.out.println("\nTraining HMM models:");
		
		for (String tag : tags.keySet()) {
			System.out.print(tag + " tag > ");
			
			TagWrapper tw = tags.get(tag);
			
			tw.trainModel();
		}
	}
	
	/**
	 * Classify an utterance given by a sequence.
	 * 
	 * @param seq
	 * @return
	 */
	public String classifyUtterance(List<ObservationInteger> seq) {
		String bestMatch = null; 
		double maxProb = -1;
		
		for (String tag : tags.keySet()) {
			TagWrapper tw = tags.get(tag);
			double prob = tw.getProbability(seq);
//			System.out.println(tag + " => " + prob);
			if (prob > maxProb) {
				bestMatch = tag;
				maxProb = prob;
			}
		}
		
		return bestMatch;
	}
	
	public void testFile(String filepath) {
		Reader reader;
		try {
			reader = new FileReader(filepath);
			List<List<ObservationInteger>> sequences = ObservationSequencesReader.readSequences(new ObservationIntegerReader(), reader);
			reader.close();
			
			for (List<ObservationInteger> seq : sequences) {
				String result = classifyUtterance(seq);
//				System.out.println(result);
			}			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public int testTagFile(String tag, String filepath, PrintWriter pw, Hashtable<String,ArrayList<Integer>> summary) {
		Reader reader;
		int match = 0;
		int uttCnt = 0;
		int matchRate = -1;
		
		ArrayList<Integer> track = new ArrayList<Integer>();
		
		try {
			reader = new FileReader(filepath);
			List<List<ObservationInteger>> sequences = ObservationSequencesReader.readSequences(new ObservationIntegerReader(), reader);
			reader.close();

			BufferedReader bf = new BufferedReader(new FileReader("text/test" + tag));
			
			for (List<ObservationInteger> seq : sequences) {
				String bestMatch = classifyUtterance(seq);
				String utterance = bf.readLine();
				if (tag.compareTo(bestMatch) == 0) match ++;
				uttCnt ++;
				pw.println(utterance + " " + bestMatch + "(" + tags.get(bestMatch).getProbability(seq)
						+ ") [" + tag + " (" + tags.get(tag).getProbability(seq) + ")]");
/*				pw.format("%s %s (%.6f) [%s (%.6f)]\n", utterance, bestMatch,
						tags.get(bestMatch).getProbability(seq), tag, tags.get(tag).getProbability(seq));*/
			}
			
			bf.close();
			
			if (uttCnt == 0) return matchRate;
			matchRate = (match * 100) / uttCnt;
			track.add(matchRate);
			track.add(match);
			track.add(uttCnt);
			summary.put(tag, track);
			System.out.println(tag + " match rate: " + matchRate + "% [" + match + "/" + uttCnt + "]");
			pw.println(tag + " match rate: " + matchRate + "% [" + match + "/" + uttCnt + "]\n\n");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return matchRate;
	}
}
